using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Runtime.Serialization;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using System.CodeDom;
using MNS.Activities.Editors.TimeEditor;
using System.Drawing.Design;
using MNS.Activities.Common;

namespace MNS.Activities
{
    [ToolboxBitmap(typeof(IteratorActivity), "Resources.ParallelIfActivity.png")]
    [ToolboxItem(typeof(IteratorToolboxItem))]
    [Designer(typeof(IteratorDesigner))]
    [ActivityValidator(typeof(IteratorValidator))]
    public partial class IteratorActivity : CompositeActivity, IActivityEventListener<ActivityExecutionStatusChangedEventArgs>
    {
        public static readonly DependencyProperty IterationQuontityProperty = DependencyProperty.Register("IterationQuontity",
            typeof(int?),
            typeof(IteratorActivity),
            new PropertyMetadata(new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible),
                new BrowsableAttribute(true),
                new DescriptionAttribute("IterationQuontity"),
                new CategoryAttribute("Data")));

        public int? IterationQuontity
        {
            get { return (int?)base.GetValue(IteratorActivity.IterationQuontityProperty); }
            set { base.SetValue(IteratorActivity.IterationQuontityProperty, value); }
        }

        public static readonly DependencyProperty TimeFromProperty = DependencyProperty.Register("TimeFrom",
            typeof(DateTime?),
            typeof(IteratorActivity),
            new PropertyMetadata(new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible),
                new BrowsableAttribute(true),
                new DescriptionAttribute("TimeFrom"),
                new CategoryAttribute("Data")));

        public DateTime? TimeFrom
        {
            get { return (DateTime?)base.GetValue(IteratorActivity.TimeFromProperty); }
            set { base.SetValue(IteratorActivity.TimeFromProperty, value); }
        }

        public static readonly DependencyProperty TimeTillProperty = DependencyProperty.Register("TimeTill",
            typeof(DateTime?),
            typeof(IteratorActivity),
            new PropertyMetadata(new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible),
                new BrowsableAttribute(true),
                new DescriptionAttribute("TimeTillProperty"),
                new CategoryAttribute("Data")));

        public DateTime? TimeTill
        {
            get { return (DateTime?)base.GetValue(IteratorActivity.TimeTillProperty); }
            set { base.SetValue(IteratorActivity.TimeTillProperty, value); }
        }

        //[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        //[Browsable(true)]
        //[Description("Dt")]
        //[Category("Data")]
        //[Editor(typeof(TimeUIEditorType), typeof(UITypeEditor))]
        //public DateTime Dt { get; set; }


        protected DateTime? _Dt = null;
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [Browsable(true)]
        [Description("Dt")]
        [Category("Data")]
        //[Editor(typeof(TimeUIEditorType), typeof(UITypeEditor))]
        public DateTime Dt
        {
            get
            {
                if (_Dt.HasValue)
                    return _Dt.Value;
                return DateTime.Now.Date;
            }
            set { _Dt = value; }
        }

        protected Time _Tt = null;
        [Editor(typeof(TimeUIEditorType), typeof(UITypeEditor))]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [Browsable(true)]
        [Description("Tt")]
        [Category("Data")]
        //[Editor(typeof(TimeUIEditorType), typeof(UITypeEditor))]
        public Time Tt
        {
            get
            {
                if (_Tt != null)
                    return _Tt;
                return new Time() { Hours = 0, Minutes = 0, Seconds = 0, MilliSeconds = 0 };
            }
            set { _Tt = value; }
        }

        protected int? _MegaCount = null;
        public int MegaCount
        {
            get { return _MegaCount ?? 0; }
            set { _MegaCount = value; }
        }

        protected int CurrentCount { get; set; }

        protected bool WhileCondition()
        {
            return CurrentCount < MegaCount;
        }


        /// <summary>
        /// Constructor
        /// </summary>
        public IteratorActivity()
	    {
		    InitializeComponent();
	    }

        /// <summary>
        /// Execute the activity and any children
        /// </summary>
        /// <param name="executionContext"></param>
        /// <returns></returns>
        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            //MegaCount = 2;

            if (null == executionContext)
                throw new ArgumentNullException("executionContext");

            // Set the flag to indicate that I am executing
            //this.IsExecuting = true;
            //bool hasStarted = true;

            var activity = this.EnabledActivities[0];

            if (WhileCondition())
            {
                CurrentCount++;
                ActivityExecutionContext context2 = executionContext.ExecutionContextManager.CreateExecutionContext(activity);
                context2.Activity.RegisterForStatusChange(Activity.ClosedEvent, this);
                context2.ExecuteActivity(context2.Activity);
            }
            else
            {
                return ActivityExecutionStatus.Closed;
            }
            
            return ActivityExecutionStatus.Executing;
        }

        /// <summary>
        /// Method called when a child activity has closed
        /// </summary>
        /// <param name="sender">The ActivityExecutionContext</param>
        /// <param name="e">Event Arguments</param>
        void IActivityEventListener<ActivityExecutionStatusChangedEventArgs>.OnEvent(object sender, ActivityExecutionStatusChangedEventArgs e)
        {
            if (null == sender)
                throw new ArgumentNullException("sender");
            if (null == e)
                throw new ArgumentException("e");

            ActivityExecutionContext context = sender as ActivityExecutionContext;

            if (null == context)
                throw new ArgumentException("The sender must be an ActivityExecutionContext", "sender");


            e.Activity.UnregisterForStatusChange(Activity.ClosedEvent, this);
            ActivityExecutionContextManager executionContextManager = context.ExecutionContextManager;
            ActivityExecutionContext context2 = executionContextManager.GetExecutionContext(e.Activity);
            executionContextManager.CompleteExecutionContext(context2);

            if (WhileCondition())
            {
                CurrentCount++;
                var activity = this.EnabledActivities[0];
                ActivityExecutionContext context3 = executionContextManager.CreateExecutionContext(activity);
                context3.Activity.RegisterForStatusChange(Activity.ClosedEvent, this);
                context3.ExecuteActivity(context3.Activity);
            }
            else
            {
                context.CloseActivity();
            }

        }
    }
}
